﻿Imports System
Imports System.Collections.Generic

Namespace System.Workflow.Activities.Rules
    Friend Class IntellisenseParser
        ' Methods
        Friend Sub New(ByVal inputString As String)
            Dim scanner As New Scanner(inputString)
            Me.tokens.Add(New Token(TokenID.EndOfInput, 0, Nothing))
            scanner.TokenizeForIntellisense(Me.tokens)
        End Sub

        Friend Function BackParse() As ParserContext
            Me.tokenIndex = (Me.tokens.Count - 1)
            If (Me.tokenIndex < 0) Then
                Return Nothing
            End If
            Dim currentToken As Token = Me.CurrentToken
            Dim flag As Boolean = False
            If (currentToken.TokenID = TokenID.EndOfInput) Then
                currentToken = Me.PrevToken
            End If
            Dim tokenIndex As Integer = Me.tokenIndex
            If (((currentToken.TokenID = TokenID.Identifier) AndAlso (CStr(currentToken.Value).Length = 1)) AndAlso (Me.PrevToken.TokenID <> TokenID.Dot)) Then
                flag = True
            ElseIf (currentToken.TokenID = TokenID.Dot) Then
                flag = Me.BackParsePostfix
            ElseIf ((currentToken.TokenID = TokenID.LParen) AndAlso (Me.PrevToken.TokenID = TokenID.Identifier)) Then
                If (Me.PrevToken.TokenID = TokenID.Dot) Then
                    flag = Me.BackParsePostfix
                Else
                    flag = True
                End If
                If (flag AndAlso (Me.CurrentToken.TokenID = TokenID.New)) Then
                    Me.PrevToken
                End If
            End If
            If Not flag Then
                Return Nothing
            End If
            Dim range As List([Of] Token) = Me.tokens.GetRange((Me.tokenIndex + 1), (tokenIndex - Me.tokenIndex))
            range.Add(New Token(TokenID.EndOfInput, 0, Nothing))
            Return New ParserContext(range)
        End Function

        Private Function BackParseMatchingDelimiter(ByVal openDelimiter As TokenID) As Boolean
            Dim tokenID As TokenID = Me.CurrentToken.TokenID
            Dim num As Integer = 1
            Dim token As Token = Me.PrevToken
            Do While (token.TokenID <> TokenID.EndOfInput)
                If (token.TokenID = tokenID) Then
                    num += 1
                ElseIf (token.TokenID = openDelimiter) Then
                    num -= 1
                    If (num = 0) Then
                        Me.PrevToken
                        Exit Do
                    End If
                End If
                token = Me.PrevToken
            Loop
            Return (num = 0)
        End Function

        Private Function BackParsePostfix() As Boolean
            Do While (Me.CurrentToken.TokenID = TokenID.Dot)
                Select Case Me.PrevToken.TokenID
                    Case TokenID.This
                        Me.PrevToken
                        Return True
                    Case TokenID.TypeName, TokenID.Identifier
                        Me.PrevToken
                        [Continue]
                    Case TokenID.RBracket
                        Do
                            If Not Me.BackParseMatchingDelimiter(TokenID.LBracket) Then
                                Return False
                            End If
                        Loop While (Me.CurrentToken.TokenID = TokenID.RBracket)
                        If (Me.CurrentToken.TokenID = TokenID.Identifier) Then
                            Me.PrevToken
                            [Continue]
                        End If
                        If (Me.CurrentToken.TokenID <> TokenID.RParen) Then
                            Return False
                        End If
                        If Not Me.BackParseMatchingDelimiter(TokenID.LParen) Then
                            Return False
                        End If
                        If (Me.CurrentToken.TokenID = TokenID.Identifier) Then
                            Me.PrevToken
                            [Continue]
                        End If
                        Return True
                    Case TokenID.RParen
                        If Not Me.BackParseMatchingDelimiter(TokenID.LParen) Then
                            Return False
                        End If
                        If (Me.CurrentToken.TokenID = TokenID.Identifier) Then
                            Me.PrevToken
                            [Continue]
                        End If
                        Return True
                    Case TokenID.Greater
                        Exit Select
                    Case Else
                        Return False
                End Select
                If (Me.BackParseMatchingDelimiter(TokenID.Less) AndAlso (Me.CurrentToken.TokenID = TokenID.Identifier)) Then
                    Me.PrevToken
                Else
                    Return False
                End If
            Loop
            If (Me.CurrentToken.TokenID = TokenID.New) Then
                Me.PrevToken
            End If
            Return True
        End Function

        Private Function PrevToken() As Token
            If (Me.tokenIndex > 0) Then
                Me.tokenIndex -= 1
            End If
            Return Me.CurrentToken
        End Function


        ' Properties
        Private ReadOnly Property CurrentToken As Token
            Get
                Return Me.tokens.Item(Me.tokenIndex)
            End Get
        End Property


        ' Fields
        Private tokenIndex As Integer
        Private tokens As List([Of] Token) = New List([Of] Token)
    End Class
End Namespace

